#include "TaskHotAreaBase.hpp"
#include "TaskGps.hpp"
#include "TaskObstacle.hpp"
#include "TaskTrafficLight.hpp"
#include "Util/BridgeIOConfig.hpp"
//#include "TaskPrediction.hpp"

TaskHotAreaManager::TaskHotAreaManager()
{
	//mIsSubscribeHotArea = false;
	mbIsSendConfig = false;
}

TaskHotAreaManager::~TaskHotAreaManager()
{
}
void TaskHotAreaManager::Init(CybertronBridgeIO* app) {
	mpApp = app;
	CTaskHotAreaBase* pTask = 0;
	pTask = new CTaskGps();
	mHotAreaTaskMap[pTask->GetTaskType()] = pTask;

	pTask = new CTaskTrafficLight();
	mHotAreaTaskMap[pTask->GetTaskType()] = pTask;

	pTask = new CTaskObstacle();
	mHotAreaTaskMap[pTask->GetTaskType()] = pTask;
}


void TaskHotAreaManager::OneHotAreaTaskEnter() {
	for (TaskHotAreaMap::iterator it = mHotAreaTaskMap.begin(); it != mHotAreaTaskMap.end(); it++){
		it->second->HotAreaEnter();
	}
}

void TaskHotAreaManager::OneHotAreaTaskSend(std::string hostVehicleId,int frame) {
	for (TaskHotAreaMap::iterator it = mHotAreaTaskMap.begin(); it != mHotAreaTaskMap.end(); it++) {
		char* msg = it->second->GetResult(hostVehicleId);
		if (msg == nullptr) continue;
		int length = it->second->GetHotAreaDataLength(hostVehicleId);
		sendHotAreaMessage(it->second->GetCommandId(), atoi(hostVehicleId.c_str()), frame, msg, length);
		it->second->Clear();
	}
}

void TaskHotAreaManager::sendHotAreaMessage(int commanId, int mainVehicleId, int frame, char* pBuffer, int length) {

	Bridge::HotAreaAnyDataMessage hotAraeMessage;

	Bridge::BridgeHotAreaHeader *header = hotAraeMessage.mutable_header();

	std::uint64_t timestamp = std::uint64_t(std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::system_clock::now().time_since_epoch()).count() / 1000.0);
	header->set_commandid(commanId);
	header->set_version(3);
	header->set_timestamp(timestamp);
	header->set_frame(frame);
	header->set_mainvehicleid(mainVehicleId);
	header->mutable_currenttime()->set_startnodetime(timestamp);
	header->mutable_currenttime()->set_bridgeiorecvtime(timestamp);
	header->mutable_currenttime()->set_bridgeiosendtime(timestamp);

	std::string* pData = hotAraeMessage.mutable_buffer();

	pData->resize(length);

	if (pData->size() > 0)
	{
		memcpy(&(pData->operator[](0)), pBuffer, length);
	}
	Message msg;
	msg.fromProtobuf(Bridge::EHotAreaAnyDataMessage, hotAraeMessage);
	mpApp->SendHotareaDataSuberMainVehicle(mainVehicleId, &msg);
}
void TaskHotAreaManager::HotAreaOnFrame(int frame, int ms, int msModNs) {
	NodeHotAreaManager* manager = mpApp->GetHotAreaManager();
	MainVehicleMap::iterator it ;
	bool bFind = false;
	for (it = mMainVehicleMap.begin(); it!= mMainVehicleMap.end(); it++){
		if (it->second.IsReady == 0){
				MainVehicleStatus mainVehicleStauts;
				mainVehicleStauts.mainVehicleId = it->first;
				mainVehicleStauts.name = "mainVehicle";
				mainVehicleStauts.IsReady = 1;
				mMainVehicleMap[it->first] = mainVehicleStauts;
				mpApp->SendMainVehicleChangeReady(it->first);
				logInfo("=======HotAreaOnFrameSendMainVehicleChangeReady=======");
				std::this_thread::sleep_for(std::chrono::milliseconds(500));
		}
	}
	
	const std::vector<std::shared_ptr<TrafficActorHotArea>> &hotAreas =
		manager->getSubscribedHotAreas();
	OneHotAreaTaskEnter();
	for (const auto& pHotArea : hotAreas) {
		int vehicleId = pHotArea->getId();
		MainVehicleMap::iterator it = mMainVehicleMap.find(vehicleId);
		if (it== mMainVehicleMap.end()) {
			//continue;
		}
		int index = 0;
		for (const auto& actorId : pHotArea->getActorIdSet()) {
			const TrafficActor &actor = pHotArea->getActor(actorId);
			//
			if (actor.getRuntimeId() == vehicleId) {
				TaskHotAreaMap::iterator it = mHotAreaTaskMap.find(TaskTypeGPS);
				if (it != mHotAreaTaskMap.end()) {
					it->second->ActorToDo(vehicleId,frame, ms, msModNs, (TrafficActorHotArea*)&(*pHotArea), (TrafficActor*)&actor, index);
				}				
			}
			//
			if (actor.getActorType() == HotArea::EActorType_TrafficLight) {
				TaskHotAreaMap::iterator it = mHotAreaTaskMap.find(TaskTypeTrafficLight);
				if (it != mHotAreaTaskMap.end()) {
					it->second->ActorToDo(vehicleId,frame, ms, msModNs, (TrafficActorHotArea*)&(*pHotArea), (TrafficActor*)&actor, index);
				}			
				index++;
			}
			//
			if (actor.getRuntimeId() != vehicleId && actor.getActorType() != HotArea::EActorType_TrafficLight) {
				TaskHotAreaMap::iterator it = mHotAreaTaskMap.find(TaskTypeObstacle);
				it->second->ActorToDo(vehicleId,frame, ms, msModNs, (TrafficActorHotArea*)&(*pHotArea), (TrafficActor*)&actor, index);
			}
		}
		OneHotAreaTaskSend(std::to_string(vehicleId),frame);
	}
}
void TaskHotAreaManager::SendMainVehicleList(SocketBasePtr pSender) {
	Bridge::BridgeResultMainVehicleList MainVehicleListInfo;
	
	for (auto it = mMainVehicleMap.begin(); it != mMainVehicleMap.end(); it++)
	{
		auto item = MainVehicleListInfo.add_mainvehicle_info();
		item->set_id(it->first);
		item->set_type(it->second.name);
	}
	
	Message msg;
	msg.fromProtobuf(Bridge::EBridgeResultMainVehicleList, MainVehicleListInfo);
	pSender->send(msg);
	return;
}
TaskHotAreaManager &TaskHotAreaManager::getInstance()
{
	static TaskHotAreaManager me;
	return me;
}